package xml;

import model.*;

import com.thoughtworks.xstream.converters.*;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class MazeConverter implements Converter {

	//XML Tags
	private static final String DIRECTION_XML_TAG = "dir";
	private static final String TILE_XML_TAG = "tile";
	private static final String TILE_MATRIX_XML_TAG = "tile-matrix";
	private static final String PASS_DOTS_XML_TAG = "passDots";
	private static final String MAX_Y_COORD_XML_TAG = "maxY";
	private static final String MAX_X_COORD_XML_TAG = "maxX";

	@Override
	public void marshal(Object source, HierarchicalStreamWriter writer,
			MarshallingContext context) {
		Maze maze = (Maze)source;
		writer.startNode(MAX_X_COORD_XML_TAG);
		writer.setValue(((Integer)maze.getMaxX()).toString());
		writer.endNode();
		writer.startNode(MAX_Y_COORD_XML_TAG);
		writer.setValue(((Integer)maze.getMaxY()).toString());
		writer.endNode();
		writer.startNode(PASS_DOTS_XML_TAG);
		writer.setValue(((Integer)maze.getPassDots()).toString());
		writer.endNode();
		writer.startNode(TILE_MATRIX_XML_TAG);
		for(int i = 0; i < maze.getMaxX(); i ++)
			for(int j = 0; j < maze.getMaxY(); j++){
				if(maze.getTile(i,j) != null){
					writer.startNode(TILE_XML_TAG);
					context.convertAnother(maze.getTile(i,j));
					writer.endNode();
				}
			}
		writer.endNode();
		
	}

	@Override
	public Object unmarshal(HierarchicalStreamReader reader,
			UnmarshallingContext context) {
		//Generate the maze object
				
		reader.moveDown();
		int x = Integer.parseInt(reader.getValue());
		reader.moveUp();
		
		reader.moveDown();
		int y = Integer.parseInt(reader.getValue());
		reader.moveUp();

		Maze maze = new Maze(x,y,false);
		
		reader.moveDown();
		maze.setPassDots(Integer.parseInt(reader.getValue()));
		reader.moveUp();
		
		Tile tile;
		Direction dir;
		reader.moveDown();
		while(reader.hasMoreChildren()){
			
			reader.moveDown();
			reader.moveDown();
			x = Integer.parseInt(reader.getValue());
			reader.moveUp();
			
			reader.moveDown();
			y = Integer.parseInt(reader.getValue());
			reader.moveUp();
			
			if(maze.getTile(x, y) == null) maze.addExitlessTile(x, y);
			tile = maze.getTile(x, y);
			
			reader.moveDown();
			Boolean temp = (Boolean)context.convertAnother(null, Boolean.class);
			tile.setVisited(temp);
			reader.moveUp();
			
			while(reader.hasMoreChildren()){
				reader.moveDown();
				dir = Enum.valueOf(Direction.class, reader.getAttribute(DIRECTION_XML_TAG));
				
				reader.moveDown();
				x = Integer.parseInt(reader.getValue());
				reader.moveUp();
				
				reader.moveDown();
				y = Integer.parseInt(reader.getValue());
				reader.moveUp();
				
				reader.moveUp();
				if(maze.getTile(x,y) == null) maze.addExitlessTile(x, y);
				tile.setExit(dir, maze.getTile(x, y));
			}
			
			reader.moveUp();
		}
		reader.moveUp();
		
		return maze;
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean canConvert(Class type) {
		return type.equals(Maze.class);
	}

}
